from datetime import datetime, timedelta
import enum
from app.api.deps import CurrentUser, SessionDep
from app.models import Device, Project, Record, Task
from fastapi import APIRouter
from sqlalchemy import func
from sqlmodel import SQLModel, and_, exists, select
from loguru import logger

router = APIRouter(prefix="/dashboard", tags=["dashboard"])


class ProjectType(enum.Enum):
    ALL = "all"
    SINGLE_PROJECT = "single_project"


class DashboardInfo(SQLModel):
    devices_total_num: int
    device_running_num: int
    devices_online_num: int
    tasks_total_num: int
    tasks_running_num: int
    project_num: int | None = None
    project_running_num: int | None = None
    scripts_total_num: int
    scripts_passed_num: int
    scripts_failed_num: int


class DashboardResponse(SQLModel):
    project_type: ProjectType
    data: DashboardInfo


@router.get("/project/{project_id}")
async def get_dashboard_data(project_id: str, session: SessionDep):
    devices_total_num = 0
    device_running_num = 0
    devices_online_num = 0
    tasks_total_num = 0
    tasks_running_num = 0
    project_num = None
    project_running_num: int | None = None
    scripts_total_num = 0
    scripts_passed_num = 0
    scripts_failed_num = 0
    if project_id == "0":
        project_type = ProjectType.ALL
        tasks_total_num = session.exec(select(func.count(Task.id))).first()
        tasks_running_num = session.exec(
            select(func.count(Task.id)).where(Task.status == 1)
        ).one()
        scripts_total_num = session.exec(select(func.count(Record.id))).first()
        scripts_passed_num = session.exec(
            select(func.count(Record.id)).where(Record.result == True)
        ).first()
        scripts_failed_num = session.exec(
            select(func.count(Record.id)).where(Record.result != True)
        ).first()
        project_num = session.exec(select(func.count(Project.id))).first()

        project_latest_status = (
            select(func.count(Task.status))
            .where(Task.project_id == Project.id, Task.status == 1)
            .scalar_subquery()
        )

        project_running_num = session.exec(
            select(func.count(Project.id)).where(project_latest_status > 0)
        ).one()

    else:
        project_type = ProjectType.SINGLE_PROJECT
        tasks_total_num = session.exec(
            select(func.count(Task.id)).where(Task.project_id == project_id)
        ).first()
        tasks_running_num = session.exec(
            select(func.count(Task.id)).where(
                Task.status == 1, Task.project_id == project_id
            )
        ).one()
        scripts_total_num = session.exec(
            select(func.count(Record.id))
            .join(Task, Task.id == Record.task_id)
            .where(Task.project_id == project_id)
        ).first()
        scripts_passed_num = session.exec(
            select(func.count(Record.id)).join(Task, Task.id == Record.task_id).where(Record.result == True, Task.project_id == project_id)
        ).first()
        scripts_failed_num = session.exec(
            select(func.count(Record.id)).join(Task, Task.id == Record.task_id).where(Record.result != True, Task.project_id == project_id)
        ).first()

    # 获取设备总数和在线设备数
    devices_total_num = session.exec(select(func.count(Device.id))).first()
    devices_online_num = session.exec(
        select(func.count(Device.id)).where(
            datetime.now() - Device.last_online < timedelta(seconds=30)
        )
    ).first()
    # 构造标量子查询：获取该设备最新任务的状态
    latest_status = (
        select(Task.status).where(Task.device_id == Device.id).order_by(Task.create_time.desc()).limit(1)
    ).scalar_subquery()

    # 查询：统计最新任务状态不等于 1 的设备数量
    device_running_num = session.exec(
        select(func.count(Device.id)).where(latest_status == 1)
    ).one()  # .one() 返回单一数值

    info = DashboardInfo(
        devices_total_num=devices_total_num,
        device_running_num=device_running_num,
        devices_online_num=devices_online_num,
        tasks_total_num=tasks_total_num,
        tasks_running_num=tasks_running_num,
        project_num=project_num,
        project_running_num=project_running_num,
        scripts_total_num=scripts_total_num,
        scripts_passed_num=scripts_passed_num,
        scripts_failed_num=scripts_failed_num,
    )
    resp = DashboardResponse(project_type=project_type, data=info)
    return resp
